<template>
  <div class="validate-input-container">
    <input
      v-model="model"
      class="form-control"
      :class="{ 'is-invalid': error }"
      @blur="validateInput"
      v-bind="$attrs"
    />
    <p v-if="error" class="invalid-feedback">{{ message }}</p>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, inject } from "vue";
import type { Emitter } from "mitt";
import type { ValidateFunc } from "../types";

interface RuleProp {
  type: "required" | "email" | "custom";
  message: string;
}
export type RulesProp = RuleProp[];

defineOptions({
  inheritAttrs: false,
});

const emitter = inject("emitter") as Emitter<{
  "form-item-created": ValidateFunc;
}>;
const model = defineModel<string>({ default: "" });
const props = defineProps<{
  rules: RulesProp;
}>();
const error = ref(false);
const message = ref("");
const emailReg =
  /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;

const validateInput = () => {
  if (props.rules) {
    const allPassed = props.rules.every((rule) => {
      let passed = true;
      message.value = rule.message;

      switch (rule.type) {
        case "required":
          passed = model.value.trim() !== "";
          break;
        case "email":
          passed = emailReg.test(model.value);
          break;
        default:
          break;
      }

      return passed;
    });

    error.value = !allPassed;
    return allPassed;
  }

  return true;
};

onMounted(() => {
  emitter.emit("form-item-created", validateInput);
});
</script>

<style scoped>
.validate-input-container {
  input {
    width: 100%;
    line-height: 1.5;
    box-sizing: border-box;
    padding: 6px 12px;
  }

  .invalid-feedback {
    margin-top: 4px;
    color: #dc3545;
  }
}
</style>
